home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / addpcx.zip / PCX.C < prev    next >
C/C++ Source or Header  |  1988-06-21  |  11KB  |  476 lines

  1. /*    PCX.c -  Graphic Routines that operate on PCX pictures
  2. */
  3.  
  4.  
  5. #include <stdio.h>
  6. #include "lib.h"
  7. #include "pcx.h"
  8.  
  9.  
  10. int pcx_init();
  11. int pcx_clear();
  12. int pcx_set_point();
  13. int pcx_clr_point();
  14. int pcx_xor_point();
  15. int pcx_write_row();
  16. int pcx_select_plane();
  17. int pcx_set_palette();
  18. int pcx_mode();
  19. int movmem();
  20. int pokeb();
  21. int peekb();
  22. int pcx_get_point();
  23.  
  24. static int (*pcx_func[])() = {
  25.     pcx_init,      pcx_clear,     pcx_set_point, pcx_clr_point,
  26.     pcx_xor_point, pcx_get_point, pcx_write_row, pcx_select_plane,
  27.     pcx_set_palette,pcx_mode,     movmem, peekb, pokeb };
  28.  
  29. PCXPIC *pcx_cpic;      /* current picture   */
  30. static int cplane;     /* current plane     */
  31. int    pcx_md;        /* 1 if CGA-type picture, 0 for HERC/EGA */
  32.  
  33.  
  34. int pcx_init()
  35. {
  36.     movmem( pcx_func, vgr_func, sizeof(vgr_func) );
  37.  
  38.     VGR_NBPL = VGR_HRES = VGR_VRES = VGR_NCOLORS = cplane = 0;
  39.     if ( pcx_cpic )
  40.     {  VGR_HRES    = pcx_cpic->hdr.hres;
  41.        VGR_VRES    = pcx_cpic->hdr.vres;
  42.        VGR_NBPL    = pcx_cpic->hdr.bpl;
  43.        VGR_NCOLORS = pcx_cpic->hdr.bpp > 1 ? 
  44.                      0x01 << pcx_cpic->hdr.bpp :
  45.                      0x01 << pcx_cpic->hdr.nplanes;
  46.     };
  47.  
  48.     return OK;
  49. }
  50.  
  51.  
  52. int pcx_select_plane( plane )
  53. int plane;
  54. {
  55.     return cplane = plane & 0x03;
  56. }
  57.  
  58.  
  59. int pcx_write_row( row, prow, nbytes )
  60. int nbytes, row;
  61. char *prow;
  62. {
  63.     int i;
  64.  
  65.     i = pcx_cpic->hdr.hres / 8;
  66.     movmem( prow, (pcx_cpic->rows[cplane][row]), 
  67.                    nbytes <= i ? nbytes : i );
  68. }
  69.  
  70.  
  71. int pcx_clear()
  72. {
  73.     int plane, row, nplanes, nrows, bytes;
  74.  
  75.     nplanes =  pcx_cpic->hdr.nplanes;
  76.     nrows   =  pcx_cpic->hdr.y2 - pcx_cpic->hdr.y1 +1;
  77.     bytes   =  pcx_cpic->hdr.bpl;
  78.  
  79.     for ( plane=0; plane < nplanes; plane ++ )
  80.        for ( row=0; row < bytes; row++ )
  81.           setmem( (pcx_cpic->rows[plane][row]), bytes, 0 );
  82. }
  83.  
  84.  
  85. int pcx_mode( m )
  86. int m;
  87. {
  88.     switch ( m )
  89.     {  case MODE_APA0:   /* 640x350x16 */
  90.        case MODE_APA1:   /* 720x348x02 */
  91.        case MODE_APA2:   /* 640x200x02 */
  92.           /* all these modes save color information
  93.              1 bit per plane.
  94.           */
  95.           pcx_md = 0;
  96.           break;
  97.        case MODE_APA3:   /* 320x200x04 */
  98.           /* this mode puts two bits per pixel into the
  99.              same plane.
  100.           */
  101.           pcx_md = 1;
  102.           break;
  103.        default:          /* invalid!   */
  104.           return ERROR;
  105.     };
  106.  
  107.     return OK;
  108. }
  109.  
  110.  
  111. int pcx_xor_point( x, y, color )
  112. int x, y, color;
  113. {
  114.     return pcx_set_point( x, y, pcx_get_point( x, y ) ^ color );
  115. }
  116.  
  117.  
  118. int pcx_clr_point( x, y )
  119. int x, y;
  120. {
  121.     return pcx_set_point( x, y, 0 );
  122. }
  123.  
  124.  
  125. int pcx_set_point( x, y, color )
  126. int x, y, color;
  127. {
  128.     register unsigned char *p;
  129.     unsigned char plane, b, o, mask;
  130.  
  131.     if ( pcx_md )
  132.     {  o = (x & 3) << 1;
  133.        p = (unsigned char *)pcx_cpic->rows[0][y] + (x>>2);
  134.        *p = (*p & ~(0xc0 >> o)) | ((color & 0x03) << (6-o));
  135.        return OK;
  136.     };
  137.  
  138.     o = x >> 3;
  139.     b = (unsigned int)0x80 >> (x & 0x07);
  140.  
  141.     for ( mask=1,plane=0; plane < pcx_cpic->hdr.nplanes; plane++, mask<<=1 )
  142.     {  p = (unsigned char *)pcx_cpic->rows[plane][y] + o;
  143.        if ( color & mask )
  144.           *p |= b;
  145.        else *p &= ~b;
  146.     };
  147.  
  148.     return OK;
  149. }
  150.  
  151.  
  152. int pcx_get_point( x, y )
  153. int x, y;
  154. {
  155.     unsigned char plane, b, o, color;
  156.  
  157.     if ( pcx_md )
  158.     {  b = (x & 3) << 1;
  159.        return ( pcx_cpic->rows[0][y][x>>2] & (0xc0 >> b) ) >> (6-b);
  160.     };
  161.  
  162.     o = x >> 3;
  163.     b = (unsigned int)0x80 >> (x & 0x07);
  164.  
  165.     for ( color=plane=0; plane < pcx_cpic->hdr.nplanes; plane++ )
  166.        color |= !!(pcx_cpic->rows[plane][y][o] & b) << plane;
  167.  
  168.     return color;
  169. }
  170.  
  171.  
  172. /*    PCX Palette Settings.
  173. */
  174.  
  175. int pcx_set_palette( reg, red, green, blue )
  176. unsigned char reg, red, green, blue;
  177. {
  178.     if ( pcx_md )
  179.     {  pcx_cpic->hdr.triple[reg].red = red;
  180.        return OK;
  181.     };
  182.  
  183.     /* why do we multiply by 85? */
  184.     pcx_cpic->hdr.triple[reg].red   = red   * 85;
  185.     pcx_cpic->hdr.triple[reg].green = green * 85;
  186.     pcx_cpic->hdr.triple[reg].blue  = blue  * 85;
  187.     return OK;
  188. }
  189.  
  190.  
  191. PCXPIC *pcx_init_pic( hres, vres, nplanes )
  192. unsigned int hres, vres, nplanes;
  193. {
  194.     int y, p, bpl;
  195.     PCXPIC *pic;
  196.     char *calloc();
  197.     static TRIPLET ega_pal[] = {  /* copied from a        */
  198.           0x00, 0x00, 0x00,       /* PBRUSH picture file  */
  199.           0x00, 0x00, 0xaa,
  200.           0x00, 0xaa, 0x00,
  201.           0x00, 0xaa, 0xaa,
  202.           0xaa, 0x00, 0x00,
  203.           0xaa, 0x00, 0xaa,
  204.           0xaa, 0xaa, 0x00,
  205.           0xaa, 0xaa, 0xaa,
  206.           0x55, 0x55, 0x55,
  207.           0x55, 0x55, 0xff,
  208.           0x55, 0xff, 0x55,
  209.           0x55, 0xff, 0xff,
  210.           0xff, 0x55, 0x55,
  211.           0xff, 0x55, 0xff,
  212.           0xff, 0xff, 0x55,
  213.           0xff, 0xff, 0xff        };
  214.  
  215.     static TRIPLET cga_pal[] = {
  216.             0,0,0, 255,0,0,
  217.             0,0,0, 255,0,0,
  218.             0,0,0, 255,0,0,
  219.             0,0,0, 255,0,0,
  220.             0,0,0, 255,0,0,
  221.             0,0,0, 255,0,0,
  222.             0,0,0, 255,0,0,
  223.             0,0,0, 255,0,0        };
  224.  
  225.     if ( !(pic = (PCXPIC *) calloc( 1, sizeof(PCXPIC) )) )
  226.        return NULL; /* out of memory */
  227.  
  228.     pic->hdr.x2 = hres -1;
  229.     pic->hdr.y2 = vres -1;
  230.  
  231.     pic->hdr.maker     = 10;
  232.     pic->hdr.version   =  5;
  233.     pic->hdr.code      =  1;
  234.     pic->hdr.bpp       =  1 + pcx_md;
  235.     pic->hdr.bpl       = bpl = (hres * (1+pcx_md)) / 8;
  236.  
  237.     VGR_HRES    = pic->hdr.hres    = hres;
  238.     VGR_VRES    = pic->hdr.vres    = vres;
  239.     VGR_NBPL    = bpl;
  240.     VGR_NCOLORS = 1 << (pic->hdr.nplanes = nplanes);
  241.  
  242.     movmem( (pcx_md ? cga_pal : ega_pal), 
  243.              pic->hdr.triple, sizeof(pic->hdr.triple) );
  244.  
  245.     for ( p=0; p < nplanes; p++ )
  246.     {  if ( ! (pic->rows[p] = (uchar **)calloc( 1, sizeof(char *) * vres)) )
  247.           return pcx_free_pic( pic ), (PCXPIC *)0;
  248.        for ( y=0; y < vres; y++ )
  249.           if ( !(pic->rows[p][y] = (uchar *)calloc( 1, bpl )) )
  250.              return pcx_free_pic( pic ), (PCXPIC *)0;
  251.     };
  252.  
  253.     return pic;
  254. }
  255.  
  256.  
  257. int pcx_free_pic( pic )
  258. PCXPIC *pic;
  259. {
  260.     int row, plane, nrows, nplan;
  261.  
  262.     nrows = pic->hdr.y2 - pic->hdr.y1 +1;
  263.     nplan = pic->hdr.nplanes;
  264.  
  265.     for ( plane = 0; plane < nplan; plane++ )
  266.     {  for ( row = 0; row < nrows; row++ )
  267.           allocf( pic->rows[plane][row] );
  268.        allocf( pic->rows[plane] );
  269.     };
  270.  
  271.     allocf( pic );
  272.     return NULL;
  273. }
  274.  
  275.  
  276. void map_not( map, len )
  277. register unsigned int *map, len;
  278. {
  279.     for ( ; len--; map++ )
  280.        *map = ~ *map;
  281. }
  282.  
  283.  
  284. void pcx_invert_pic( pic )
  285. PCXPIC *pic;
  286. {
  287.     int p, r, i;
  288.  
  289.     for ( p=0; p < pic->hdr.nplanes; p++ )
  290.        for ( r=0; r < (pic->hdr.y2 - pic->hdr.y1); r++ )
  291.           map_not( pic->rows[p][r], pic->hdr.bpl / 2 );
  292. }
  293.  
  294.  
  295. allocf( p )
  296. char *p;
  297. {
  298.     if ( !p )
  299.        return OK;
  300.  
  301.     if ( free(p) == -1 )
  302.        CRASH( "heap munged" );
  303. }
  304.  
  305. #ifdef MAIN
  306.  
  307. /*    Manx 'C stack/heap size adjustment -
  308.     The vgr_fill() function uses an enourmous amount of stack,
  309.     and we're going to need enough heap space to allocate
  310.     4 bit maps for the EGA board.
  311. */
  312. uint    __STKLOW = 0,
  313.         __STKSIZ = 4096,
  314.         __HEAPSIZ = 8192;
  315.  
  316. int     cga_init(), ega_init(), herc_init();
  317. int    board, (*board_init)(), md;
  318.  
  319. /*    This structure is used here to facilitate drawing the
  320.     simple X and complex box that are used to test the
  321.     dot, line and fill functions.
  322. */
  323. typedef struct {
  324.    int x,y;
  325. } OBJ;
  326.  
  327. static OBJ obj[] = { 
  328. 100, 100, 150, 200, 200, 100, 250, 150, 175, 250, 250, 350, 200, 400, 150, 300, 
  329. 100, 400,  50, 350, 125, 250,  50, 150, 100, 100 };
  330.  
  331. static OBJ obj2[] = {
  332.   0,  0,280,  0,280,140,240,140,240, 20,200, 20,200,280,240,280,240,160, 
  333. 280,160,280,300,  0,300,  0,160, 40,160, 40,280, 80,280, 80, 20, 40, 20, 
  334.  40,140,  0,140,  0,  0 };
  335.        
  336. static OBJ obj3[] = {
  337.        120,20, 160,20, 160,280, 120,280, 120,20 };
  338.  
  339.  
  340. main( argc, argv )
  341. char **argv;
  342. int argc;
  343. {
  344.     void pcx_showpic();
  345.     FILE *fp, *fopen();
  346.     int c, h, v, p;
  347.  
  348.     printf("PCX test routine.\n");
  349.     if ( argc == 1 )
  350.        printf("Try \"PCX xx\" for help\n" );
  351.  
  352.     board = vgr_get_board();
  353.  
  354.     if ( argc >= 2 )
  355.     {       if ( !strcmp(argv[1], "ega") )
  356.                board = TYPE_EGA;
  357.        else if ( !strcmp(argv[1], "cga") )
  358.                board = TYPE_CGA;
  359.        else if ( !strcmp(argv[1], "herc") )
  360.                board = TYPE_HERC;
  361.        else if ( !strcmp(argv[1], "cga2") )
  362.                board = 9;
  363.        else {  printf("\
  364. usage: PCX\n\
  365. or     PCX <board>\n\
  366. or     PCX <board> <pcx_file_name>\n\n\
  367.  func: Excercises the board & PCX routines.\n\
  368.        <board> may be one of:\n\
  369.               cga - 640x200x2 CGA\n\
  370.               cga2- 320x200x4 CGA\n\
  371.               herc- Hercules Hi-Res\n\
  372.               ega - 640x350x16 EGA\n\
  373.        <pcx_file_name> may be any file name,\n\
  374.        although an extension of .PCX is\n\
  375.        appropriate.\n" );
  376.                 exit(1);
  377.              };
  378.     };
  379.  
  380.     switch( board )
  381.     {  case TYPE_UNKNOWN:
  382.        case TYPE_MDA:
  383.           CRASH("unable to detect a HERC, CGA or EGA board");
  384.        case TYPE_CGA:
  385.           printf("CGA board detected\n");
  386.           board_init = cga_init;
  387.           md = MODE_APA2, c = 1, h = 640, v=200, p=1;
  388.           break;
  389.        case 9:
  390.           printf("CGA/APA3 Selected\n");
  391.           board_init = cga_init;
  392.           md = MODE_APA3, c = 2, h = 320, v=200, p=1;
  393.           break;
  394.        case TYPE_EGA:
  395.           printf("EGA board detected\n");
  396.           board_init = ega_init;
  397.           md = MODE_APA0, c = 9, h = 640, v=350, p=4;
  398.           break;
  399.        case TYPE_HERC:
  400.           printf("HERC board detected\n");
  401.           board_init = herc_init;
  402.           md = MODE_APA1, c = 1, h = 720, v=348, p=1;
  403.           break;
  404.        default:
  405.           CRASH("bug: invalid board type number");
  406.     };
  407.  
  408.     printf("Hit return to continue:");
  409.     getchar();
  410.  
  411.     /* pcx_init_pic needs to know what mode it's in
  412.     */
  413.     pcx_init();
  414.     pcx_mode( md );   
  415.     if ( !(pcx_cpic = pcx_init_pic( h, v, p )) )
  416.        CRASH("out of memory");
  417.  
  418.     pcx_init();
  419.     if ( VGR_MODE( md ) )
  420.        CRASH( "error in mode selection" );
  421.  
  422.     printf("HRES=%d, VRES=%d, NCOLORS=%d, NPLANES=%d, pcx_md=%d\n",
  423.           VGR_HRES, VGR_VRES, VGR_NCOLORS, p, pcx_md );
  424.  
  425.     draw_it( (OBJ *)&obj,  NELEMS(obj) , 3, 3,   0, 0, c );
  426.     printf(".");
  427.     draw_it( (OBJ *)&obj2, NELEMS(obj2), 3, 3, 150, 0, c );
  428.     printf(".");
  429.     draw_it( (OBJ *)&obj3, NELEMS(obj3), 3, 3, 150, 0, c );
  430.     printf(".");
  431.  
  432.     vgr_fill(  33, 40, c );
  433.     printf(".");
  434.     vgr_fill( 179, 19, c );
  435.  
  436.     printf("\nhit return to continue, then hit return again:");
  437.     getchar();
  438.  
  439.     if ( (*board_init)() )
  440.        CRASH( "board init failed" );
  441.     if ( VGR_MODE( md ) )
  442.        CRASH( "error in mode selection" );
  443.  
  444.     pcx_showpic( pcx_cpic, 0, 0, 0 );
  445.  
  446.     getchar();
  447.  
  448.     VGR_MODE( MODE_TEXT0 );
  449.  
  450.     if ( argc == 3 )
  451.     {  if ( !(fp = fopen( argv[2], "w" )) )
  452.           CRASH( "error opening picture file" );
  453.        if ( pcx_write_pic( pcx_cpic, fp ) )
  454.           CRASH( "error writing picture file" );
  455.        fclose(fp);
  456.     };
  457.  
  458.     exit(0);
  459. }
  460.  
  461.  
  462. draw_it( obj, n, divx, divy, ox, oy, c )
  463. OBJ *obj;
  464. int n, divx, divy;
  465. {
  466.     int x;
  467.  
  468.     vgr_point( obj[0].x / divx + ox, obj[0].y / divy + oy, -1 );
  469.     for ( x=1; x < n; x++ )
  470.        vgr_point( obj[x].x / divx + ox, obj[x].y / divy + oy, c );
  471. }
  472.  
  473.  
  474. #endif
  475.  
  476.